package com.run_java_test.t.test_run2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.tools.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;

@Component
public class DynamicControllerManager {

    @Autowired
    private ConfigurableApplicationContext applicationContext;

    public void registerController(String javaCode) throws Exception {
        // 1. 动态编译 Java 代码
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

        // 输出目录
        File outputDir = new File("dynamic_classes");
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }
        fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList(outputDir));

        // 源代码文件
        JavaFileObject file = new InMemoryJavaFileObject("DynamicController", javaCode);

        // 动态编译
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, Collections.singletonList(file));
        if (!task.call()) {
            throw new RuntimeException("Compilation failed");
        }
        fileManager.close();

        // 2. 加载类
        URLClassLoader classLoader = new URLClassLoader(
                new URL[]{outputDir.toURI().toURL()},
                this.getClass().getClassLoader());
        Class<?> dynamicClass = classLoader.loadClass("DynamicController");

        // 3. 移除旧的映射
        String beanName = "dynamicController";
        if (applicationContext.containsBean(beanName)) {
            removeExistingMapping(beanName);
        }

        // 4. 注册新的 Controller
        applicationContext.getBeanFactory().registerSingleton(beanName, dynamicClass.getDeclaredConstructor().newInstance());

        // 5. 重新初始化 RequestMappingHandlerMapping，注册新的 Controller 映射
        reinitializeRequestMappingHandler(dynamicClass);
    }

    private void removeExistingMapping(String beanName) {
        RequestMappingHandlerMapping handlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);

        // 获取旧的 Controller 对象
        Object controller = applicationContext.getBean(beanName);
        if (controller != null) {
            // 移除旧的映射
            handlerMapping.getHandlerMethods()
                    .entrySet()
                    .removeIf(entry -> entry.getValue().getBean().equals(controller));
        }
    }

    private void reinitializeRequestMappingHandler(Object bean) throws Exception {
        RequestMappingHandlerMapping handlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);

        // 获取 detectHandlerMethods 方法
        Method detectHandlerMethods = AbstractHandlerMethodMapping.class.getDeclaredMethod("detectHandlerMethods", Object.class);
        detectHandlerMethods.setAccessible(true); // 设置可访问

        // 调用 detectHandlerMethods 注册新的 Controller
        detectHandlerMethods.invoke(handlerMapping, bean);
    }
}
